package com.qezhhnjy.demo.schedule.custom;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.PeriodicTrigger;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * @author zhaoyangfu - 2021/1/4 13:49
 * 通过自定义 taskScheduler 来配置调度线程池
 * 通过 configureTasks 来执行任务，同时可以动态更新定时机制, 通过更新trigger可以更新调度机制
 */
@Configuration
@EnableScheduling
@Slf4j
public class CustomSchedule implements SchedulingConfigurer {

    PeriodicTrigger trigger = new PeriodicTrigger(3, TimeUnit.SECONDS);

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> log.info(LocalDateTime.now().toString()),
                triggerContext -> trigger.nextExecutionTime(triggerContext));
    }


    /**
     * 默认使用单线程执行定时任务
     * 注入后使用 `taskScheduler` 的bean作为调度线程池
     * 也可在configureTasks方法中手动注入
     */
    @Bean(destroyMethod = "shutdown")
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(3);
        taskScheduler.setThreadNamePrefix("Scheduled-");
        taskScheduler.setRejectedExecutionHandler((r, e) -> {
            if (!e.isShutdown()) {
                r.run();
            }
            // 记录执行失败的任务到数据库表中
            // 发送告警邮件给相关负责人
        });
        taskScheduler.setErrorHandler(e -> log.error(e.getMessage(), e));
        taskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        taskScheduler.setAwaitTerminationSeconds(60);
        taskScheduler.initialize();
        return taskScheduler;
    }

}
